// 《围棋》作者版权所有。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package types

import (
	"cmd/compile/internal/base"
	"cmd/internal/src"
	"fmt"
	"strings"
	"sync"
)

// 对象表示ir。节点，但不需要导入cmd/compile/internal/ir，
// 这将导致导入周期。在其他软件包中的使用必须类型assert 
// 类型Object to ir的值。节点或更具体的类型。
type Object interface {
	Pos() src.XPos
	Sym() *Sym
	Type() *Type
}

// 类型对象是表示命名类型的对象。
type TypeObject interface {
	Object
	TypeDefn() *Type // 对于“typet Defn”，返回Defn 
}

// go:generate stringer-type Kind-trimtype。go 

// Kind描述了一种类型。
type Kind uint8

const (
	Txxx Kind = iota

	TINT8
	TUINT8
	TINT16
	TUINT16
	TINT32
	TUINT32
	TINT64
	TUINT64
	TINT
	TUINT
	TUINTPTR

	TCOMPLEX64
	TCOMPLEX128

	TFLOAT32
	TFLOAT64

	TBOOL

	TPTR
	TFUNC
	TSLICE
	TARRAY
	TSTRUCT
	TCHAN
	TMAP
	TINTER
	TFORW
	TANY
	TSTRING
	TUNSAFEPTR
	TTYPEPARAM
	TUNION

	// 文本的伪类型
	TIDEAL // 非类型化数值常量
	TNIL
	TBLANK

	// 仅在帧布局期间临时使用的伪类型（CalcSize（））
	TFUNCARGS
	TCHANARGS

	// SSA后端类型
	TSSA     // SSA后端使用的内部类型（标志、内存等）
	TTUPLE   // SSA后端使用的一对类型
	TRESULTS // 多个类型；调用函数或方法的结果，最后有一个内存。

	NTYPE
)

// ChanDir是指一个通道是否可以发送、接收或同时发送和/或接收。
type ChanDir uint8

func (c ChanDir) CanRecv() bool { return c&Crecv != 0 }
func (c ChanDir) CanSend() bool { return c&Csend != 0 }

const (
	// 频道类型
	// 必须匹配../..
	Crecv ChanDir = 1 << 0
	Csend ChanDir = 1 << 1
	Cboth ChanDir = Crecv | Csend
)

// 类型存储指向预先声明的命名类型的指针。
// 
// 它还存储指向几种特殊类型的指针：
// /-types[TANY]是子参数类型识别的占位符“any”类型。ABCFDG
// /-Types[TINTER]是规范的“接口{}”类型。
// /-Types[TNIL]表示预先声明的“nil”值的类型。
// /-Types[TUNSAFEPTR]是包的指针类型。
var Types [NTYPE]*Type

var (
	// 预先声明的别名类型。它们实际上被创建为不同的
	// 定义的类型，以获得更好的错误消息，但随后被特别地
	// 视为与各自的基础类型相同。
	AnyType  *Type
	ByteType *Type
	RuneType *Type

	// 预声明的错误接口类型。
	ErrorType *Type
	// 预先声明的可比较接口类型。
	ComparableType *Type

	// 表示非类型化字符串和布尔常量的类型。
	UntypedString = newType(TSTRING)
	UntypedBool   = newType(TBOOL)

	// 表示非类型化数值常量的类型。
	UntypedInt     = newType(TIDEAL)
	UntypedRune    = newType(TIDEAL)
	UntypedFloat   = newType(TIDEAL)
	UntypedComplex = newType(TIDEAL)
)

// 一个类型代表一个Go类型。
// 
// 可能有多个结构相同的未命名类型。但是，对于每个唯一的命名（定义）类型，必须有一个唯一的类型对象。点点头后，可以通过构建其唯一符号sym（sym=
// 包级别类型。Def。如果是sym。Def为非nil，
// package.Lookup（name））并检查sym来查找
// 类型已存在于软件包范围内，并可在sym获得。Def。（*ir.名称）。类型（）。
// 本地类型（可能与包级别的类型同名）由vargen的值区分。
type Type struct {
	// extra包含额外的特定于etype的字段。
	// 作为一种优化，那些完全包含一个指针形字段的特定于etype的结构尽可能存储为值而不是指针。
	// 
	// TMAP:*地图
	// TFORW:*前进
	// TFUNC:*函数
	// T结构：*结构
	// TINTER:*接口
	// TFUNCARGS:FuncArgs 
	// TSLICE:Slice 
	// TSSA:string 
	// TTYPEPARAM:*Typeparam 
	// TUNION:*Union 
	extra interface{}

	// width是该类型的宽度，以字节为单位。
	width int64 // 如果Align>0则有效

	// 基本方法列表（不包括嵌入）
	methods Fields
	// 所有方法列表（包括嵌入）
	allMethods Fields

	// 命名类型的规范OTYPE节点（应为具有相同符号的ir.Name节点）
	nod Object
	// 定义类型的基础类型（类型文字或预声明类型）
	underlying *Type

	// 的缓存复合类型，该类型为元素类型。
	cache struct {
		ptr   *Type // /*T，或nil 
		slice *Type // /[]T，或nil 
	}

	sym    *Sym  // 包含名称的符号，用于命名类型
	vargen int32 // OTYPE/ONAME 

	kind  Kind  // 类型
	align uint8 // 此类型所需的对齐方式，字节（0表示尚未计算宽度和对齐方式）

	flags bitset8

	// 用于已定义（命名）的泛型，指向需要实例化的该类型的类型params 
	// /（按顺序）列表的指针。对于实例化的
	// 泛型类型，这是用于实例化它们的TARG。这些TARG 
	// 可能是typeparams（用于重新实例化的类型，如Value[T2]）或
	// 具体类型（用于完全实例化的类型，如Value[int]）。
	// rparams仅为泛型或完全从泛型类型实例化的命名类型设置，否则设置为nil。
	// TODO（danscales）：选择一个更好的名字。
	rparams *[]*Type

	// 对于实例化的泛型类型，为基泛型类型。
	// 这个反向指针很有用，因为基类型是包含
	// 方法体的类型。
	origType *Type
}

func (*Type) CanBeAnSSAAux() {}

const (
	typeNotInHeap  = 1 << iota // 类型不能被堆分配
	typeBroke                  // 类型定义被破坏
	typeNoalg                  // 禁止哈希和eq算法生成
	typeDeferwidth             // 宽度计算被延迟，类型处于延迟状态
	typeRecur
	typeHasTParam // 类型（泛型函数或类型）中某处有一个typeparam相关类型，对于泛型
	typeHasShape  // 类型
)

func (t *Type) NotInHeap() bool  { return t.flags&typeNotInHeap != 0 }
func (t *Type) Broke() bool      { return t.flags&typeBroke != 0 }
func (t *Type) Noalg() bool      { return t.flags&typeNoalg != 0 }
func (t *Type) Deferwidth() bool { return t.flags&typeDeferwidth != 0 }
func (t *Type) Recur() bool      { return t.flags&typeRecur != 0 }
func (t *Type) HasTParam() bool  { return t.flags&typeHasTParam != 0 }
func (t *Type) IsShape() bool    { return t.flags&typeIsShape != 0 }
func (t *Type) HasShape() bool   { return t.flags&typeHasShape != 0 }

func (t *Type) SetNotInHeap(b bool)  { t.flags.set(typeNotInHeap, b) }
func (t *Type) SetBroke(b bool)      { t.flags.set(typeBroke, b) }
func (t *Type) SetNoalg(b bool)      { t.flags.set(typeNoalg, b) }
func (t *Type) SetDeferwidth(b bool) { t.flags.set(typeDeferwidth, b) }
func (t *Type) SetRecur(b bool)      { t.flags.set(typeRecur, b) }

// 中有一个形状，泛型类型永远不应该有alg函数。
func (t *Type) SetHasTParam(b bool) { t.flags.set(typeHasTParam, b); t.flags.set(typeNoalg, b) }

// 在执行SetIsShape（true）时，应始终执行SetHashape（true）。
func (t *Type) SetIsShape(b bool)  { t.flags.set(typeIsShape, b) }
func (t *Type) SetHasShape(b bool) { t.flags.set(typeHasShape, b) }

// Kind返回类型t的类型。
func (t *Type) Kind() Kind { return t.kind }

// Sym返回类型t的名称。
func (t *Type) Sym() *Sym       { return t.sym }
func (t *Type) SetSym(sym *Sym) { t.sym = sym }

// OrigType返回t是
// 实例化的原始泛型类型（如果有）。
func (t *Type) OrigType() *Type        { return t.origType }
func (t *Type) SetOrigType(orig *Type) { t.origType = orig }

// underground返回类型t的底层类型。
func (t *Type) Underlying() *Type { return t.underlying }

// SetNod将t与语法节点n相关联。
func (t *Type) SetNod(n Object) {
	// t.nod在共享*类型（如[]字节或接口{}）的情况下可以是非零的。
	if t.nod == nil {
		t.nod = n
	}
}

// Pos返回与t相关的位置（如果有）。
// 这只能用于诊断。
func (t *Type) Pos() src.XPos {
	if t.nod != nil {
		return t.nod.Pos()
	}
	return src.NoXPos
}

func (t *Type) RParams() []*Type {
	if t.rparams == nil {
		return nil
	}
	return *t.rparams
}

func (t *Type) SetRParams(rparams []*Type) {
	if len(rparams) == 0 {
		base.Fatalf("Setting nil or zero-length rparams")
	}
	t.rparams = &rparams
	// 如果任何rparam是或具有类型param，则应设置HasTParam。这是
	// 用于处理不引用其任何
	// 类型参数（例如，最常见的是空结构）的泛型类型的情况。
	for _, rparam := range rparams {
		if rparam.HasTParam() {
			t.SetHasTParam(true)
			break
		}
		if rparam.HasShape() {
			t.SetHasShape(true)
			break
		}
	}
}

// 如果t是泛型类型（未使用
// 重新实例化另一个类型参数或完全实例化），则IsBaseGeneric返回true。如果t是已使用
func (t *Type) IsBaseGeneric() bool {
	return len(t.RParams()) > 0 && strings.Index(t.Sym().Name, "[") < 0
}

// 重新实例化新类型参数（即未完全实例化）的泛型类型，则IsInstalledGeneric返回t。
func (t *Type) IsInstantiatedGeneric() bool {
	return len(t.RParams()) > 0 && strings.Index(t.Sym().Name, "[") >= 0 &&
		t.HasTParam()
}

// IsFullyInstantiated报告t是否为完全实例化的泛型类型；i、 e.一个
// 实例化的泛型类型，其中所有类型参数都是非泛型或完全
// 实例化的泛型类型。
func (t *Type) IsFullyInstantiated() bool {
	return len(t.RParams()) > 0 && !t.HasTParam()
}

// NoPkg是一个为清晰起见的零*Pkg值。
// 用于构造未导出的类型，因此不需要与任何包关联。
var NoPkg *Pkg = nil

// Pkg返回t出现在中的包。
// 
// Pkg仅为函数、结构和接口类型
// （即具有命名元素的类型）定义。这些信息不是由
// cmd/compile本身使用的，但我们需要跟踪它，因为它是由
// go/types API公开的。
func (t *Type) Pkg() *Pkg {
	switch t.kind {
	case TFUNC:
		return t.extra.(*Func).pkg
	case TSTRUCT:
		return t.extra.(*Struct).pkg
	case TINTER:
		return t.extra.(*Interface).pkg
	default:
		base.Fatalf("Pkg: unexpected kind: %v", t)
		return nil
	}
}

// 映射包含特定于映射的类型字段。
type Map struct {
	Key  *Type // 密钥类型
	Elem *Type // Val（elem）类型

	Bucket *Type // 表示散列桶的内部结构类型
	Hmap   *Type // 表示Hmap（映射头对象）的内部结构类型
	Hiter  *Type // 表示散列迭代器状态的内部结构类型
}

// MapType返回t额外的特定于映射的字段。
func (t *Type) MapType() *Map {
	t.wantEtype(TMAP)
	return t.extra.(*Map)
}

// 转发包含特定于转发类型的类型字段。
type Forward struct {
	Copyto      []*Type  // 在何处将最终值复制到
	Embedlineno src.XPos // 首次将此类型用作嵌入类型
}

// ForwardType返回t的额外转发类型特定字段。
func (t *Type) ForwardType() *Forward {
	t.wantEtype(TFORW)
	return t.extra.(*Forward)
}

// Func包含特定于Func类型的类型字段。
type Func struct {
	Receiver *Type // 函数接收器
	Results  *Type // 函数结果
	Params   *Type // 函数参数
	TParams  *Type // 接收器类型参数（如果方法）或函数

	pkg *Pkg

	// Argwid是函数接收器、参数和结果的总宽度。
	// 它通过临时TFUNCARGS类型进行计算。
	// 请注意，TFUNC的宽度是Widthptr。
	Argwid int64
}

// FuncType返回t的额外func特定字段。
func (t *Type) FuncType() *Func {
	t.wantEtype(TFUNC)
	return t.extra.(*Func)
}

// StructType包含特定于结构类型的类型字段。
type Struct struct {
	fields Fields
	pkg    *Pkg

	// 映射有三个关联的内部结构（请参见结构映射类型）。
	// 映射将此类结构链接回其映射类型。
	Map *Type

	Funarg Funarg // arg struct的函数参数类型
}

// fnstuct记录函数参数的类型
type Funarg uint8

const (
	FunargNone    Funarg = iota
	FunargRcvr           // 接收器
	FunargParams         // 输入参数
	FunargResults        // 输出结果
	FunargTparams        // 类型参数
)

// StructType返回t的额外结构特定字段。
func (t *Type) StructType() *Struct {
	t.wantEtype(TSTRUCT)
	return t.extra.(*Struct)
}

// 接口包含特定于接口类型的类型字段。
type Interface struct {
	pkg      *Pkg
	implicit bool
}

// Typeparam包含特定于Typeparam类型的类型字段。
type Typeparam struct {
	index int // 以源代码顺序从0开始的类型参数索引
	bound *Type
}

// Union包含特定于Union类型的类型字段。
type Union struct {
	terms  []*Type
	tildes []bool // 术语[i]的格式是否为~T 
}

// Ptr包含特定于指针类型的类型字段。
type Ptr struct {
	Elem *Type // 元素类型
}

// ChanArgs包含特定于TCHANARGS类型的类型字段。
type ChanArgs struct {
	T *Type // 对其元素需要进行宽度检查的chan类型的引用
}

// /FuncArgs包含特定于TFUNCARGS类型的类型字段。
type FuncArgs struct {
	T *Type // 对其元素需要宽度检查的func类型的引用
}

// Chan包含特定于通道类型的类型字段。
type Chan struct {
	Elem *Type   // 元素类型
	Dir  ChanDir // 通道方向
}

// ChanType返回t的额外通道特定字段。
func (t *Type) ChanType() *Chan {
	t.wantEtype(TCHAN)
	return t.extra.(*Chan)
}

type Tuple struct {
	first  *Type
	second *Type
	// 任何内存类型的元组都必须将该内存类型放在第二位。
}

// 结果是延迟扩展的调用的输出。
type Results struct {
	Types []*Type // 最后一个元素是调用的内存输出。
}

// 数组包含特定于数组类型的类型字段。
type Array struct {
	Elem  *Type // 元素类型
	Bound int64 // 元素数<0如果未知但
}

// 切片包含特定于切片类型的类型字段。
type Slice struct {
	Elem *Type // 元素类型
}

// 字段是一个（Sym，type）配对以及一些其他信息，并且，
// 取决于上下文，用于表示：
// -结构中的字段
// -接口中的方法或与命名类型
// -函数参数
type Field struct {
	flags bitset8

	Embedded uint8 // /嵌入字段

	Pos src.XPos

	// /字段名称/方法/参数。接口和未命名参数中嵌入
	// 的接口字段可以为零。
	Sym  *Sym
	Type *Type  // 字段类型
	Note string // 文字字符串注释

	// 对于表示函数参数的字段，Nname指向与ONAME节点关联的
	// 字段。对于表示方法的字段，Nname指向
	// 函数名节点。
	Nname Object

	// 此字段或方法在其封闭结构
	// 或接口类型中的偏移量（字节）。例外情况：如果字段是函数接收器、arg或
	// 结果，则这是伪FUNARG偏移量；类型不知道Abi。
	Offset int64
}

const (
	fieldIsDDD = 1 << iota // 字段为。。。参数
	fieldBroke             // 断开的字段定义
	fieldNointerface
)

func (f *Field) IsDDD() bool       { return f.flags&fieldIsDDD != 0 }
func (f *Field) Broke() bool       { return f.flags&fieldBroke != 0 }
func (f *Field) Nointerface() bool { return f.flags&fieldNointerface != 0 }

func (f *Field) SetIsDDD(b bool)       { f.flags.set(fieldIsDDD, b) }
func (f *Field) SetBroke(b bool)       { f.flags.set(fieldBroke, b) }
func (f *Field) SetNointerface(b bool) { f.flags.set(fieldNointerface, b) }

// End返回紧跟在该字段后面的第一个字节的偏移量。
func (f *Field) End() int64 {
	return f.Offset + f.Type.width
}

// IsMethod报告f是否表示方法而不是结构字段。
func (f *Field) IsMethod() bool {
	return f.Type.kind == TFUNC && f.Type.Recv() != nil
}

// Fields是指向*字段切片的指针。
// 与*字段的简单切片相比，这在没有字段或方法的类型中节省了空间。
type Fields struct {
	s *[]*Field
}

// Len返回f中的条目数。
func (f *Fields) Len() int {
	if f.s == nil {
		return 0
	}
	return len(*f.s)
}

// Slice将f中的条目数作为切片返回。
// 切片条目的更改将反映在f中。
func (f *Fields) Slice() []*Field {
	if f.s == nil {
		return nil
	}
	return *f.s
}

// 索引返回字段的第i个元素。
// 如果f至少没有i+1元素，它就会恐慌。
func (f *Fields) Index(i int) *Field {
	return (*f.s)[i]
}

// 将f设置为切片。
// 这是片的所有权。
func (f *Fields) Set(s []*Field) {
	if len(s) == 0 {
		f.s = nil
	} else {
		// 复制s并获取t而不是s的地址，以避免在len（s）==0的情况下进行分配。
		t := s
		f.s = &t
	}
}

// Append将条目追加到f。
func (f *Fields) Append(s ...*Field) {
	if f.s == nil {
		f.s = new([]*Field)
	}
	*f.s = append(*f.s, s...)
}

// New返回指定类型的新类型。
func newType(et Kind) *Type {
	t := &Type{
		kind:  et,
		width: BADWIDTH,
	}
	t.underlying = t
	// TODO（约书亚）：懒洋洋地初始化其中一些？
	switch t.kind {
	case TMAP:
		t.extra = new(Map)
	case TFORW:
		t.extra = new(Forward)
	case TFUNC:
		t.extra = new(Func)
	case TSTRUCT:
		t.extra = new(Struct)
	case TINTER:
		t.extra = new(Interface)
	case TPTR:
		t.extra = Ptr{}
	case TCHANARGS:
		t.extra = ChanArgs{}
	case TFUNCARGS:
		t.extra = FuncArgs{}
	case TCHAN:
		t.extra = new(Chan)
	case TTUPLE:
		t.extra = new(Tuple)
	case TRESULTS:
		t.extra = new(Results)
	case TTYPEPARAM:
		t.extra = new(Typeparam)
	case TUNION:
		t.extra = new(Union)
	}
	return t
}

// NewArray返回一个新的固定长度数组类型。
func NewArray(elem *Type, bound int64) *Type {
	if bound < 0 {
		base.Fatalf("NewArray: invalid bound %v", bound)
	}
	t := newType(TARRAY)
	t.extra = &Array{Elem: elem, Bound: bound}
	t.SetNotInHeap(elem.NotInHeap())
	if elem.HasTParam() {
		t.SetHasTParam(true)
	}
	if elem.HasShape() {
		t.SetHasShape(true)
	}
	return t
}

// NewSlice返回元素类型为elem的切片类型。
func NewSlice(elem *Type) *Type {
	if t := elem.cache.slice; t != nil {
		if t.Elem() != elem {
			base.Fatalf("elem mismatch")
		}
		if elem.HasTParam() != t.HasTParam() || elem.HasShape() != t.HasShape() {
			base.Fatalf("Incorrect HasTParam/HasShape flag for cached slice type")
		}
		return t
	}

	t := newType(TSLICE)
	t.extra = Slice{Elem: elem}
	elem.cache.slice = t
	if elem.HasTParam() {
		t.SetHasTParam(true)
	}
	if elem.HasShape() {
		t.SetHasShape(true)
	}
	return t
}

// NewChan返回一个带有direction dir的新chan类型。
func NewChan(elem *Type, dir ChanDir) *Type {
	t := newType(TCHAN)
	ct := t.ChanType()
	ct.Elem = elem
	ct.Dir = dir
	if elem.HasTParam() {
		t.SetHasTParam(true)
	}
	if elem.HasShape() {
		t.SetHasShape(true)
	}
	return t
}

func NewTuple(t1, t2 *Type) *Type {
	t := newType(TTUPLE)
	t.extra.(*Tuple).first = t1
	t.extra.(*Tuple).second = t2
	if t1.HasTParam() || t2.HasTParam() {
		t.SetHasTParam(true)
	}
	if t1.HasShape() || t2.HasShape() {
		t.SetHasShape(true)
	}
	return t
}

func newResults(types []*Type) *Type {
	t := newType(TRESULTS)
	t.extra.(*Results).Types = types
	return t
}

func NewResults(types []*Type) *Type {
	if len(types) == 1 && types[0] == TypeMem {
		return TypeResultMem
	}
	return newResults(types)
}

func newSSA(name string) *Type {
	t := newType(TSSA)
	t.extra = name
	return t
}

// NewMap返回一个键类型为k、元素（aka value）类型为v的新映射类型。
func NewMap(k, v *Type) *Type {
	t := newType(TMAP)
	mt := t.MapType()
	mt.Key = k
	mt.Elem = v
	if k.HasTParam() || v.HasTParam() {
		t.SetHasTParam(true)
	}
	if k.HasShape() || v.HasShape() {
		t.SetHasShape(true)
	}
	return t
}

// newptrcachenabled控制是否在T中缓存*T类型。
// 在启动后端之前，缓存被禁用。
// 这允许后端同时运行。
var NewPtrCacheEnabled = true

// NewPtr返回指向t的指针类型。
func NewPtr(elem *Type) *Type {
	if elem == nil {
		base.Fatalf("NewPtr: pointer to elem Type is nil")
	}

	if t := elem.cache.ptr; t != nil {
		if t.Elem() != elem {
			base.Fatalf("NewPtr: elem mismatch")
		}
		if elem.HasTParam() != t.HasTParam() || elem.HasShape() != t.HasShape() {
			base.Fatalf("Incorrect HasTParam/HasShape flag for cached pointer type")
		}
		return t
	}

	t := newType(TPTR)
	t.extra = Ptr{Elem: elem}
	t.width = int64(PtrSize)
	t.align = uint8(PtrSize)
	if NewPtrCacheEnabled {
		elem.cache.ptr = t
	}
	if elem.HasTParam() {
		t.SetHasTParam(true)
	}
	if elem.HasShape() {
		t.SetHasShape(true)
	}
	return t
}

// NewChanArgs为通道类型c返回一个新的TCHANARGS类型。
func NewChanArgs(c *Type) *Type {
	t := newType(TCHANARGS)
	t.extra = ChanArgs{T: c}
	return t
}

// NewFuncArgs为func类型f返回一个新的TFUNCARGS类型。
func NewFuncArgs(f *Type) *Type {
	t := newType(TFUNCARGS)
	t.extra = FuncArgs{T: f}
	return t
}

func NewField(pos src.XPos, sym *Sym, typ *Type) *Field {
	f := &Field{
		Pos:    pos,
		Sym:    sym,
		Type:   typ,
		Offset: BADWIDTH,
	}
	if typ == nil {
		f.SetBroke(true)
	}
	return f
}

// 。它返回被替换的类型。
func SubstAny(t *Type, types *[]*Type) *Type {
	if t == nil {
		return nil
	}

	switch t.kind {
	default:
		// 保持类型不变。

	case TANY:
		if len(*types) == 0 {
			base.Fatalf("SubstArgTypes: not enough argument types")
		}
		t = (*types)[0]
		*types = (*types)[1:]

	case TPTR:
		elem := SubstAny(t.Elem(), types)
		if elem != t.Elem() {
			t = t.copy()
			t.extra = Ptr{Elem: elem}
		}

	case TARRAY:
		elem := SubstAny(t.Elem(), types)
		if elem != t.Elem() {
			t = t.copy()
			t.extra.(*Array).Elem = elem
		}

	case TSLICE:
		elem := SubstAny(t.Elem(), types)
		if elem != t.Elem() {
			t = t.copy()
			t.extra = Slice{Elem: elem}
		}

	case TCHAN:
		elem := SubstAny(t.Elem(), types)
		if elem != t.Elem() {
			t = t.copy()
			t.extra.(*Chan).Elem = elem
		}

	case TMAP:
		key := SubstAny(t.Key(), types)
		elem := SubstAny(t.Elem(), types)
		if key != t.Key() || elem != t.Elem() {
			t = t.copy()
			t.extra.(*Map).Key = key
			t.extra.(*Map).Elem = elem
		}

	case TFUNC:
		recvs := SubstAny(t.Recvs(), types)
		params := SubstAny(t.Params(), types)
		results := SubstAny(t.Results(), types)
		if recvs != t.Recvs() || params != t.Params() || results != t.Results() {
			t = t.copy()
			t.FuncType().Receiver = recvs
			t.FuncType().Results = results
			t.FuncType().Params = params
		}

	case TSTRUCT:
		// 复制所有字段，包括类型不变的字段。
		// 这可以防止函数之间出现别名，这可能会导致以后
		// 字段的偏移量被错误地覆盖。
		fields := t.FieldSlice()
		nfs := make([]*Field, len(fields))
		for i, f := range fields {
			nft := SubstAny(f.Type, types)
			nfs[i] = f.Copy()
			nfs[i].Type = nft
		}
		t = t.copy()
		t.SetFields(nfs)
	}

	return t
}

// copy返回该类型的浅拷贝。
func (t *Type) copy() *Type {
	if t == nil {
		return nil
	}
	nt := *t
	// 复制任何*T额外字段，以避免混淆
	switch t.kind {
	case TMAP:
		x := *t.extra.(*Map)
		nt.extra = &x
	case TFORW:
		x := *t.extra.(*Forward)
		nt.extra = &x
	case TFUNC:
		x := *t.extra.(*Func)
		nt.extra = &x
	case TSTRUCT:
		x := *t.extra.(*Struct)
		nt.extra = &x
	case TINTER:
		x := *t.extra.(*Interface)
		nt.extra = &x
	case TCHAN:
		x := *t.extra.(*Chan)
		nt.extra = &x
	case TARRAY:
		x := *t.extra.(*Array)
		nt.extra = &x
	case TTYPEPARAM:
		base.Fatalf("typeparam types cannot be copied")
	case TTUPLE, TSSA, TRESULTS:
		base.Fatalf("ssa types cannot be copied")
	}
	// TODO（mdempsky）：找出原因并解释。
	if t.underlying == t {
		nt.underlying = &nt
	}
	return &nt
}

func (f *Field) Copy() *Field {
	nf := *f
	return &nf
}

func (t *Type) wantEtype(et Kind) {
	if t.kind != et {
		base.Fatalf("want %v, but have %v", et, t)
	}
}

func (t *Type) Recvs() *Type   { return t.FuncType().Receiver }
func (t *Type) TParams() *Type { return t.FuncType().TParams }
func (t *Type) Params() *Type  { return t.FuncType().Params }
func (t *Type) Results() *Type { return t.FuncType().Results }

func (t *Type) NumRecvs() int   { return t.FuncType().Receiver.NumFields() }
func (t *Type) NumTParams() int { return t.FuncType().TParams.NumFields() }
func (t *Type) NumParams() int  { return t.FuncType().Params.NumFields() }
func (t *Type) NumResults() int { return t.FuncType().Results.NumFields() }

// IsVariadic报告函数类型t是否是可变的。
func (t *Type) IsVariadic() bool {
	n := t.NumParams()
	return n > 0 && t.Params().Field(n-1).IsDDD()
}

// Recv返回函数类型t的接收器（如果有）。
func (t *Type) Recv() *Field {
	s := t.Recvs()
	if s.NumFields() == 0 {
		return nil
	}
	return s.Field(0)
}

// RecvsParamsResults按顺序存储函数类型的访问器函数
// receiver、参数和结果参数。
// 它可以用于迭代函数的所有参数列表。
var RecvsParamsResults = [3]func(*Type) *Type{
	(*Type).Recvs, (*Type).Params, (*Type).Results,
}

// RecvsParams类似于RecvsParamsResults，但省略了结果参数。
var RecvsParams = [2]func(*Type) *Type{
	(*Type).Recvs, (*Type).Params,
}

// ParamsResults与RecvsParamsResults类似，但省略了接收器参数。
var ParamsResults = [2]func(*Type) *Type{
	(*Type).Params, (*Type).Results,
}

// Key返回映射类型t的键类型。
func (t *Type) Key() *Type {
	t.wantEtype(TMAP)
	return t.extra.(*Map).Key
}

// Elem返回t的元素类型。
// 可用于指针、通道、数组、切片和映射。
func (t *Type) Elem() *Type {
	switch t.kind {
	case TPTR:
		return t.extra.(Ptr).Elem
	case TARRAY:
		return t.extra.(*Array).Elem
	case TSLICE:
		return t.extra.(Slice).Elem
	case TCHAN:
		return t.extra.(*Chan).Elem
	case TMAP:
		return t.extra.(*Map).Elem
	}
	base.Fatalf("Type.Elem %s", t.kind)
	return nil
}

// ChanArgs返回TCHANARGS类型t的通道类型。
func (t *Type) ChanArgs() *Type {
	t.wantEtype(TCHANARGS)
	return t.extra.(ChanArgs).T
}

// FuncArgs返回TFUNCARGS类型t的func类型。
func (t *Type) FuncArgs() *Type {
	t.wantEtype(TFUNCARGS)
	return t.extra.(FuncArgs).T
}

// IsFuncArgStruct报告t是表示函数参数还是结果的结构。
func (t *Type) IsFuncArgStruct() bool {
	return t.kind == TSTRUCT && t.extra.(*Struct).Funarg != FunargNone
}

// 方法返回指向类型t的基方法（不包括嵌入）的指针。
// 这些方法可以是具体方法（对于非接口类型）或接口
// 方法（对于接口类型）。
func (t *Type) Methods() *Fields {
	return &t.methods
}

// AllMethods返回指向类型t的所有方法（包括嵌入）的指针。
// 对于接口类型，这是一组通常迭代的方法。对于非接口类型，AllMethods（）仅在
// CalcMethods（）至少被调用一次后返回有效结果。
func (t *Type) AllMethods() *Fields {
	if t.kind == TINTER {
		// 动态计算接口类型的完整方法集
		// 现在，如果还没有完成的话。
		CalcSize(t)
	}
	return &t.allMethods
}

// SetAllMethods为类型t设置所有方法（包括嵌入）的集合。
// 使用此方法代替t.AllMethods（）。Set（），它可能会对
// 一个未初始化的接口类型调用CalcSize（）。
func (t *Type) SetAllMethods(fs []*Field) {
	t.allMethods.Set(fs)
}

// Fields返回结构类型t的字段。
func (t *Type) Fields() *Fields {
	t.wantEtype(TSTRUCT)
	return &t.extra.(*Struct).fields
}

// Field返回结构类型t的第i个字段。
func (t *Type) Field(i int) *Field {
	return t.Fields().Slice()[i]
}

// FieldSlice返回包含结构类型t的所有字段的切片。
// a struct type t。
func (t *Type) FieldSlice() []*Field {
	return t.Fields().Slice()
}

// SetFields将结构类型t的字段设置为字段。
func (t *Type) SetFields(fields []*Field) {
	// 如果我们之前计算过t的宽度，那么其他类型，例如函数签名
	// 现在可能有错误的类型。
	// 与其尝试跟踪并使其无效，不如强制要求一旦计算了
	// t的宽度，就不能调用设置字段。
	if t.widthCalculated() {
		base.Fatalf("SetFields of %v: width previously calculated", t)
	}
	t.wantEtype(TSTRUCT)
	for _, f := range fields {
		// 如果类型T包含一个带有go:notinheap 
		// 类型的字段F，那么T也必须是go:notinheap。否则，
		// 您可以堆分配T，然后得到一个指针F，
		// 这将是一个指向go:notinheap 
		// 类型的堆指针。
		if f.Type != nil && f.Type.NotInHeap() {
			t.SetNotInHeap(true)
			break
		}
	}
	t.Fields().Set(fields)
}

// SetInterface设置接口类型t的基本方法。
func (t *Type) SetInterface(methods []*Field) {
	t.wantEtype(TINTER)
	t.Methods().Set(methods)
}

// ArgWidth返回函数的总对齐参数大小。
// 包括接收机、参数和结果。
func (t *Type) ArgWidth() int64 {
	t.wantEtype(TFUNC)
	return t.extra.(*Func).Argwid
}

func (t *Type) Size() int64 {
	if t.kind == TSSA {
		if t == TypeInt128 {
			return 16
		}
		return 0
	}
	CalcSize(t)
	return t.width
}

func (t *Type) Alignment() int64 {
	CalcSize(t)
	return int64(t.align)
}

func (t *Type) SimpleString() string {
	return t.kind.String()
}

// Cmp是值a和b之间的比较。
// -1如果a<b 
// 0如果a==b 
// 1如果a>b 
type Cmp int8

const (
	CMPlt = Cmp(-1)
	CMPeq = Cmp(0)
	CMPgt = Cmp(1)
)

// COMPAR比较类型，用于SSA back 
// end，返回Cmp（CMPlt、CMPeq、CMPgt之一）。
// 对于优化器
// 或代码生成器，答案是正确的，但不一定是类型检查。
// 选择的顺序是任意的，只有一致性和将
// 划分为等价类（比较CMPeq的类型）才重要。
func (t *Type) Compare(x *Type) Cmp {
	if x == t {
		return CMPeq
	}
	return t.cmp(x)
}

func cmpForNe(x bool) Cmp {
	if x {
		return CMPlt
	}
	return CMPgt
}

func (r *Sym) cmpsym(s *Sym) Cmp {
	if r == s {
		return CMPeq
	}
	if r == nil {
		return CMPlt
	}
	if s == nil {
		return CMPgt
	}
	// 快速排序，非精确排序
	if len(r.Name) != len(s.Name) {
		return cmpForNe(len(r.Name) < len(s.Name))
	}
	if r.Pkg != s.Pkg {
		if len(r.Pkg.Prefix) != len(s.Pkg.Prefix) {
			return cmpForNe(len(r.Pkg.Prefix) < len(s.Pkg.Prefix))
		}
		if r.Pkg.Prefix != s.Pkg.Prefix {
			return cmpForNe(r.Pkg.Prefix < s.Pkg.Prefix)
		}
	}
	if r.Name != s.Name {
		return cmpForNe(r.Name < s.Name)
	}
	return CMPeq
}

// cmp比较两个*类型t和x，返回CMPlt，
// CMPeq，CMPgt为t<x，t==x，t>x，用于任意
// 和以优化器为中心的比较概念。
// TODO（josharian）：这对于递归接口类型
// 是安全的，并用于符号列表排序。见第19869期。
func (t *Type) cmp(x *Type) Cmp {
	// 这遵循相同身份的函数结构。去
	// 有两个例外。
	// 1。由于需要<、=、>的结果，因此会更仔细地比较符号。
	//    2. 映射经过特殊处理以避免无休止的递归——映射
	// 包含一个在Go源代码中无法表达的内部数据类型。
	if t == x {
		return CMPeq
	}
	if t == nil {
		return CMPlt
	}
	if x == nil {
		return CMPgt
	}

	if t.kind != x.kind {
		return cmpForNe(t.kind < x.kind)
	}

	if t.sym != nil || x.sym != nil {
		// 特殊情况：我们将字节和uint8分开，以获取错误消息。平等对待他们。
		switch t.kind {
		case TUINT8:
			if (t == Types[TUINT8] || t == ByteType) && (x == Types[TUINT8] || x == ByteType) {
				return CMPeq
			}

		case TINT32:
			if (t == Types[RuneType.kind] || t == RuneType) && (x == Types[RuneType.kind] || x == RuneType) {
				return CMPeq
			}

		case TINTER:
			// 确保命名的任何类型都与任何空接口匹配。
			if t == AnyType && x.IsEmptyInterface() || x == AnyType && t.IsEmptyInterface() {
				return CMPeq
			}
		}
	}

	if c := t.sym.cmpsym(x.sym); c != CMPeq {
		return c
	}

	if x.sym != nil {
		// Syms非零，如果vargens匹配则等于。
		if t.vargen != x.vargen {
			return cmpForNe(t.vargen < x.vargen)
		}
		return CMPeq
	}
	// 两个符号都为零，请看下面的结构。

	switch t.kind {
	case TBOOL, TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128, TUNSAFEPTR, TUINTPTR,
		TINT8, TINT16, TINT32, TINT64, TINT, TUINT8, TUINT16, TUINT32, TUINT64, TUINT:
		return CMPeq

	case TSSA:
		tname := t.extra.(string)
		xname := x.extra.(string)
		// 想要快速排序，而不是漂亮的排序。
		if len(tname) == len(xname) {
			if tname == xname {
				return CMPeq
			}
			if tname < xname {
				return CMPlt
			}
			return CMPgt
		}
		if len(tname) > len(xname) {
			return CMPgt
		}
		return CMPlt

	case TTUPLE:
		xtup := x.extra.(*Tuple)
		ttup := t.extra.(*Tuple)
		if c := ttup.first.Compare(xtup.first); c != CMPeq {
			return c
		}
		return ttup.second.Compare(xtup.second)

	case TRESULTS:
		xResults := x.extra.(*Results)
		tResults := t.extra.(*Results)
		xl, tl := len(xResults.Types), len(tResults.Types)
		if tl != xl {
			if tl < xl {
				return CMPlt
			}
			return CMPgt
		}
		for i := 0; i < tl; i++ {
			if c := tResults.Types[i].Compare(xResults.Types[i]); c != CMPeq {
				return c
			}
		}
		return CMPeq

	case TMAP:
		if c := t.Key().cmp(x.Key()); c != CMPeq {
			return c
		}
		return t.Elem().cmp(x.Elem())

	case TPTR, TSLICE:
		// 无特殊情况，切换后按通用代码处理。

	case TSTRUCT:
		if t.StructType().Map == nil {
			if x.StructType().Map != nil {
				return CMPlt // nil<non-nil 
			}
			// to the fallthrough 
		} else if x.StructType().Map == nil {
			return CMPgt // nil>non-nil 
		} else if t.StructType().Map.MapType().Bucket == t {
			// 两者都有非nil映射
			// 对于包含递归类型的映射的特例，其中递归没有被命名类型
			if x.StructType().Map.MapType().Bucket != x {
				return CMPlt // 桶映射是最少的
			}
			return t.StructType().Map.cmp(x.StructType().Map)
		} else if x.StructType().Map.MapType().Bucket == x {
			return CMPgt // 桶映射是最少的

		tfs := t.FieldSlice()
		xfs := x.FieldSlice()
		for i := 0; i < len(tfs) && i < len(xfs); i++ {
			t1, x1 := tfs[i], xfs[i]
			if t1.Embedded != x1.Embedded {
				return cmpForNe(t1.Embedded < x1.Embedded)
			}
			if t1.Note != x1.Note {
				return cmpForNe(t1.Note < x1.Note)
			}
			if c := t1.Sym.cmpsym(x1.Sym); c != CMPeq {
				return c
			}
			if c := t1.Type.cmp(x1.Type); c != CMPeq {
				return c
			}
		}
		if len(tfs) != len(xfs) {
			return cmpForNe(len(tfs) < len(xfs))
		}
		return CMPeq

	case TINTER:
		tfs := t.AllMethods().Slice()
		xfs := x.AllMethods().Slice()
		for i := 0; i < len(tfs) && i < len(xfs); i++ {
			t1, x1 := tfs[i], xfs[i]
			if c := t1.Sym.cmpsym(x1.Sym); c != CMPeq {
				return c
			}
			if c := t1.Type.cmp(x1.Type); c != CMPeq {
				return c
			}
		}
		if len(tfs) != len(xfs) {
			return cmpForNe(len(tfs) < len(xfs))
		}
		return CMPeq

	case TFUNC:
		for _, f := range RecvsParamsResults {
			// 循环结构中的字段，忽略参数名称。
			tfs := f(t).FieldSlice()
			xfs := f(x).FieldSlice()
			for i := 0; i < len(tfs) && i < len(xfs); i++ {
				ta := tfs[i]
				tb := xfs[i]
				if ta.IsDDD() != tb.IsDDD() {
					return cmpForNe(!ta.IsDDD())
				}
				if c := ta.Type.cmp(tb.Type); c != CMPeq {
					return c
				}
			}
			if len(tfs) != len(xfs) {
				return cmpForNe(len(tfs) < len(xfs))
			}
		}
		return CMPeq

	case TARRAY:
		if t.NumElem() != x.NumElem() {
			return cmpForNe(t.NumElem() < x.NumElem())
		}

	case TCHAN:
		if t.ChanDir() != x.ChanDir() {
			return cmpForNe(t.ChanDir() < x.ChanDir())
		}

	default:
		e := fmt.Sprintf("Do not know how to compare %v with %v", t, x)
		panic(e)
	}

	// TARRAY、TCHAN、TPTR和TSLICE的常见元素类型比较。
	return t.Elem().cmp(x.Elem())
}

// IsKind报告t是否为指定类型的类型。
func (t *Type) IsKind(et Kind) bool {
	return t != nil && t.kind == et
}

func (t *Type) IsBoolean() bool {
	return t.kind == TBOOL
}

var unsignedEType = [...]Kind{
	TINT8:    TUINT8,
	TUINT8:   TUINT8,
	TINT16:   TUINT16,
	TUINT16:  TUINT16,
	TINT32:   TUINT32,
	TUINT32:  TUINT32,
	TINT64:   TUINT64,
	TUINT64:  TUINT64,
	TINT:     TUINT,
	TUINT:    TUINT,
	TUINTPTR: TUINTPTR,
}

// ToUnsigned返回整数类型t的无符号等效值。
func (t *Type) ToUnsigned() *Type {
	if !t.IsInteger() {
		base.Fatalf("unsignedType(%v)", t)
	}
	return Types[unsignedEType[t.kind]]
}

func (t *Type) IsInteger() bool {
	switch t.kind {
	case TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32, TINT64, TUINT64, TINT, TUINT, TUINTPTR:
		return true
	}
	return t == UntypedInt || t == UntypedRune
}

func (t *Type) IsSigned() bool {
	switch t.kind {
	case TINT8, TINT16, TINT32, TINT64, TINT:
		return true
	}
	return false
}

func (t *Type) IsUnsigned() bool {
	switch t.kind {
	case TUINT8, TUINT16, TUINT32, TUINT64, TUINT, TUINTPTR:
		return true
	}
	return false
}

func (t *Type) IsFloat() bool {
	return t.kind == TFLOAT32 || t.kind == TFLOAT64 || t == UntypedFloat
}

func (t *Type) IsComplex() bool {
	return t.kind == TCOMPLEX64 || t.kind == TCOMPLEX128 || t == UntypedComplex
}

// IsPtr报告t是否为常规Go指针类型。
// 这不包括不安全。指针。
func (t *Type) IsPtr() bool {
	return t.kind == TPTR
}

// IsPtrElem报告t是否是指向t的指针的元素。
func (t *Type) IsPtrElem() bool {
	return t.cache.ptr != nil
}

// IsUnsafePtr报告t是否为不安全指针。
func (t *Type) IsUnsafePtr() bool {
	return t.kind == TUNSAFEPTR
}

// isuintpttr报告t是否为uintpttr。
func (t *Type) IsUintptr() bool {
	return t.kind == TUINTPTR
}

// IsPtrShaped报告t是否由一个机器指针表示。
// 除了常规的Go指针类型外，还包括map、channel和
// 函数类型和不安全类型。指针。它不包括数组或结构类型
// 它们由一个指针形状的类型组成。
// TODO（mdempsky）：应该吗？见戈朗。org/issue/15028。
func (t *Type) IsPtrShaped() bool {
	return t.kind == TPTR || t.kind == TUNSAFEPTR ||
		t.kind == TMAP || t.kind == TCHAN || t.kind == TFUNC
}

// HasNil报告由t确定的值集是否包括nil。
func (t *Type) HasNil() bool {
	switch t.kind {
	case TCHAN, TFUNC, TINTER, TMAP, TNIL, TPTR, TSLICE, TUNSAFEPTR:
		return true
	}
	return false
}

func (t *Type) IsString() bool {
	return t.kind == TSTRING
}

func (t *Type) IsMap() bool {
	return t.kind == TMAP
}

func (t *Type) IsChan() bool {
	return t.kind == TCHAN
}

func (t *Type) IsSlice() bool {
	return t.kind == TSLICE
}

func (t *Type) IsArray() bool {
	return t.kind == TARRAY
}

func (t *Type) IsStruct() bool {
	return t.kind == TSTRUCT
}

func (t *Type) IsInterface() bool {
	return t.kind == TINTER
}

func (t *Type) IsUnion() bool {
	return t.kind == TUNION
}

func (t *Type) IsTypeParam() bool {
	return t.kind == TTYPEPARAM
}

// IsEmptyInterface报告t是否为空接口类型。
func (t *Type) IsEmptyInterface() bool {
	return t.IsInterface() && t.AllMethods().Len() == 0
}

// IsScalar报告“t”是否为标量Go类型，例如
// bool/int/float/complex。请注意，由单个标量元素的
// 组成的结构和数组类型不被视为标量，同样，
// 指针类型也不被视为标量。
func (t *Type) IsScalar() bool {
	switch t.kind {
	case TBOOL, TINT8, TUINT8, TINT16, TUINT16, TINT32,
		TUINT32, TINT64, TUINT64, TINT, TUINT,
		TUINTPTR, TCOMPLEX64, TCOMPLEX128, TFLOAT32, TFLOAT64:
		return true
	}
	return false
}

func (t *Type) PtrTo() *Type {
	return NewPtr(t)
}

func (t *Type) NumFields() int {
	if t.kind == TRESULTS {
		return len(t.extra.(*Results).Types)
	}
	return t.Fields().Len()
}
func (t *Type) FieldType(i int) *Type {
	if t.kind == TTUPLE {
		switch i {
		case 0:
			return t.extra.(*Tuple).first
		case 1:
			return t.extra.(*Tuple).second
		default:
			panic("bad tuple index")
		}
	}
	if t.kind == TRESULTS {
		return t.extra.(*Results).Types[i]
	}
	return t.Field(i).Type
}
func (t *Type) FieldOff(i int) int64 {
	return t.Field(i).Offset
}
func (t *Type) FieldName(i int) string {
	return t.Field(i).Sym.Name
}

func (t *Type) NumElem() int64 {
	t.wantEtype(TARRAY)
	return t.extra.(*Array).Bound
}

type componentsIncludeBlankFields bool

const (
	IgnoreBlankFields componentsIncludeBlankFields = false
	CountBlankFields  componentsIncludeBlankFields = true
)

// NumComponents返回组成t的基本元素的数量。
// 为了计数，结构和数组类型被展平。
// 所有其他类型（包括字符串、切片和接口类型）都算作一个元素。
// 如果countBlank是IgnoreBlankFields，则空白结构字段
// （及其组成元素）将从计数中排除。
// struct{x，y[3]int}有六个组件；[10] 结构{x，y string}有20个。
func (t *Type) NumComponents(countBlank componentsIncludeBlankFields) int64 {
	switch t.kind {
	case TSTRUCT:
		if t.IsFuncArgStruct() {
			base.Fatalf("NumComponents func arg struct")
		}
		var n int64
		for _, f := range t.FieldSlice() {
			if countBlank == IgnoreBlankFields && f.Sym.IsBlank() {
				continue
			}
			n += f.Type.NumComponents(countBlank)
		}
		return n
	case TARRAY:
		return t.NumElem() * t.Elem().NumComponents(countBlank)
	}
	return 1
}

// SoleComponent返回t中唯一的原语组件，
// 如果只有一个原语组件。否则，它返回nil。
// 组件按NumComponents计算，包括空白字段。
func (t *Type) SoleComponent() *Type {
	switch t.kind {
	case TSTRUCT:
		if t.IsFuncArgStruct() {
			base.Fatalf("SoleComponent func arg struct")
		}
		if t.NumFields() != 1 {
			return nil
		}
		return t.Field(0).Type.SoleComponent()
	case TARRAY:
		if t.NumElem() != 1 {
			return nil
		}
		return t.Elem().SoleComponent()
	}
	return t
}

// ChanDir返回通道类型t的方向。
// 该方向将是Crecv、Csend或Cboth之一。
func (t *Type) ChanDir() ChanDir {
	t.wantEtype(TCHAN)
	return t.extra.(*Chan).Dir
}

func (t *Type) IsMemory() bool {
	if t == TypeMem || t.kind == TTUPLE && t.extra.(*Tuple).second == TypeMem {
		return true
	}
	if t.kind == TRESULTS {
		if types := t.extra.(*Results).Types; len(types) > 0 && types[len(types)-1] == TypeMem {
			return true
		}
	}
	return false
}
func (t *Type) IsFlags() bool   { return t == TypeFlags }
func (t *Type) IsVoid() bool    { return t == TypeVoid }
func (t *Type) IsTuple() bool   { return t.kind == TTUPLE }
func (t *Type) IsResults() bool { return t.kind == TRESULTS }

// IsUntyped报告t是否为非类型化类型。
func (t *Type) IsUntyped() bool {
	if t == nil {
		return false
	}
	if t == UntypedString || t == UntypedBool {
		return true
	}
	switch t.kind {
	case TNIL, TIDEAL:
		return true
	}
	return false
}

// HasPointers报告t是否包含堆指针。
// 请注意，此函数忽略要转到的指针：notinheap类型。
func (t *Type) HasPointers() bool {
	return PtrDataSize(t) > 0
}

var recvType *Type

// FakeRecvType返回用于接口方法接收器的单例类型。
func FakeRecvType() *Type {
	if recvType == nil {
		recvType = NewPtr(newType(TSTRUCT))
	}
	return recvType
}

func FakeRecv() *Field {
	return NewField(src.NoXPos, nil, FakeRecvType())
}

var (
	// TSSA类型。HasPointers假定这些是无指针的。
	TypeInvalid   = newSSA("invalid")
	TypeMem       = newSSA("mem")
	TypeFlags     = newSSA("flags")
	TypeVoid      = newSSA("void")
	TypeInt128    = newSSA("int128")
	TypeResultMem = newResults([]*Type{TypeMem})
)

// NewNamed为给定的类型名返回一个新的命名类型。obj应该是
// ir。名称新类型不完整（标记为TFORW kind），基础
// 类型应稍后通过setUnderground（）设置。对该类型的引用是
// 在填写该类型之前一直保持，因此这些引用可以在
// 该类型完成时更新。
func NewNamed(obj TypeObject) *Type {
	t := newType(TFORW)
	t.sym = obj.Sym()
	t.nod = obj
	if t.sym.Pkg == ShapePkg {
		t.SetIsShape(true)
		t.SetHasShape(true)
	}
	return t
}

// Obj为命名类型t返回规范类型名节点，为未命名类型返回nil。
func (t *Type) Obj() Object {
	if t.sym != nil {
		return t.nod
	}
	return nil
}

// typeGen跟踪
// 已声明的函数作用域定义类型的数量。它用于为
// 它们的运行时类型描述符生成唯一的链接器符号。
var typeGen int32

// SetVargen为类型t分配一个唯一的生成号，该类型必须是在函数范围内声明的定义类型。
// 数字用于将其与同一软件包中其他拼写类似的
// 定义的类型区分开来。
// 
// TODO（mdempsky）：想出一个更好的解决方案。
func (t *Type) SetVargen() {
	base.Assertf(t.Sym() != nil, "SetVargen on anonymous type %v", t)
	base.Assertf(t.vargen == 0, "type %v already has Vargen %v", t, t.vargen)

	typeGen++
	t.vargen = typeGen
}

// SetUnderground设置不完整类型的基础类型（即类型
// 当前为TFORW的类型）。SetUnderground自动更新等待
// 完成此类型的所有类型。
func (t *Type) SetUnderlying(underlying *Type) {
	if underlying.kind == TFORW {
		// 此类型尚未计算；更新n.
		underlying.ForwardType().Copyto = append(underlying.ForwardType().Copyto, t)
		return
	}

	ft := t.ForwardType()

	// TODO（mdempsky）：修复类型重新点燃。
	t.kind = underlying.kind
	t.extra = underlying.extra
	t.width = underlying.width
	t.align = underlying.align
	t.underlying = underlying.underlying

	if underlying.NotInHeap() {
		t.SetNotInHeap(true)
	}
	if underlying.Broke() {
		t.SetBroke(true)
	}
	if underlying.HasTParam() {
		t.SetHasTParam(true)
	}
	if underlying.HasShape() {
		t.SetHasShape(true)
	}

	// spec:“声明的类型不继承任何绑定到现有类型的方法，而是接口
	// type[…]这一点没有改变。“
	if t.IsInterface() {
		t.methods = underlying.methods
		t.allMethods = underlying.allMethods
	}

	// 更新等待此类型的类型。
	for _, w := range ft.Copyto {
		w.SetUnderlying(t)
	}

	// 仔细检查类型作为嵌入类型的使用。
	if ft.Embedlineno.IsKnown() {
		if t.IsPtr() || t.IsUnsafePtr() {
			base.ErrorfAt(ft.Embedlineno, "embedded type cannot be a pointer")
		}
	}
}

func fieldsHasTParam(fields []*Field) bool {
	for _, f := range fields {
		if f.Type != nil && f.Type.HasTParam() {
			return true
		}
	}
	return false
}

func fieldsHasShape(fields []*Field) bool {
	for _, f := range fields {
		if f.Type != nil && f.Type.HasShape() {
			return true
		}
	}
	return false
}

// NewBasic返回给定类型的新基本类型。
func newBasic(kind Kind, obj Object) *Type {
	t := newType(kind)
	t.sym = obj.Sym()
	t.nod = obj
	return t
}

// NewInterface返回给定方法的新接口和
// 嵌入类型。嵌入类型被指定为不带符号的字段。
func NewInterface(pkg *Pkg, methods []*Field, implicit bool) *Type {
	t := newType(TINTER)
	t.SetInterface(methods)
	for _, f := range methods {
		// f.T对于中断的接口声明
		if f.Type != nil && f.Type.HasTParam() {
			t.SetHasTParam(true)
			break
		}
		if f.Type != nil && f.Type.HasShape() {
			t.SetHasShape(true)
			break
		}
	}
	if anyBroke(methods) {
		t.SetBroke(true)
	}
	t.extra.(*Interface).pkg = pkg
	t.extra.(*Interface).implicit = implicit
	return t
}

// NewTypeParam返回一个新的类型参数，该类型参数具有指定的sym（包和名称）
// 和typeparam列表中的指定索引。
func NewTypeParam(sym *Sym, index int) *Type {
	t := newType(TTYPEPARAM)
	t.sym = sym
	t.extra.(*Typeparam).index = index
	t.SetHasTParam(true)
	return t
}

// Index返回其param列表中param类型的索引。
func (t *Type) Index() int {
	t.wantEtype(TTYPEPARAM)
	return t.extra.(*Typeparam).index
}

// SetIndex在其参数列表中设置类型param的索引。
func (t *Type) SetIndex(i int) {
	t.wantEtype(TTYPEPARAM)
	t.extra.(*Typeparam).index = i
}

// SetBound设置typeparam的界限。
func (t *Type) SetBound(bound *Type) {
	t.wantEtype(TTYPEPARAM)
	t.extra.(*Typeparam).bound = bound
}

// Bound返回typeparam的绑定。
func (t *Type) Bound() *Type {
	t.wantEtype(TTYPEPARAM)
	return t.extra.(*Typeparam).bound
}

// IsImplicit报告接口是否隐式（即从类型
// 参数约束中删除）。
func (t *Type) IsImplicit() bool {
	t.wantEtype(TINTER)
	return t.extra.(*Interface).implicit
}

// MarkImplicit将接口标记为隐式。
func (t *Type) MarkImplicit() {
	t.wantEtype(TINTER)
	t.extra.(*Interface).implicit = true
}

// NewUnion返回具有指定术语集（类型）的新联合。如果
// tildes[i]为真，则术语[i]表示~T，而不仅仅是T。
func NewUnion(terms []*Type, tildes []bool) *Type {
	t := newType(TUNION)
	if len(terms) != len(tildes) {
		base.Fatalf("Mismatched terms and tildes for NewUnion")
	}
	t.extra.(*Union).terms = terms
	t.extra.(*Union).tildes = tildes
	nt := len(terms)
	for i := 0; i < nt; i++ {
		if terms[i].HasTParam() {
			t.SetHasTParam(true)
		}
		if terms[i].HasShape() {
			t.SetHasShape(true)
		}
	}
	return t
}

// NumTerms返回联合类型中的术语数。
func (t *Type) NumTerms() int {
	t.wantEtype(TUNION)
	return len(t.extra.(*Union).terms)
}

// Term返回联合类型的第i个Term（Term，tilde）。如果tilde为真，术语
// 代表~T，而不仅仅是T。
func (t *Type) Term(i int) (*Type, bool) {
	t.wantEtype(TUNION)
	u := t.extra.(*Union)
	return u.terms[i], u.tildes[i]
}

const BOGUS_FUNARG_OFFSET = -1000000000

func unzeroFieldOffsets(f []*Field) {
	for i := range f {
		f[i].Offset = BOGUS_FUNARG_OFFSET // 如果不纠正，这将导致爆炸
	}
}

// NewSignature为给定的接收器返回一个新的函数类型，
// 参数、结果和类型参数，其中任何一个都可能为零。
func NewSignature(pkg *Pkg, recv *Field, tparams, params, results []*Field) *Type {
	var recvs []*Field
	if recv != nil {
		recvs = []*Field{recv}
	}

	t := newType(TFUNC)
	ft := t.FuncType()

	funargs := func(fields []*Field, funarg Funarg) *Type {
		s := NewStruct(NoPkg, fields)
		s.StructType().Funarg = funarg
		if s.Broke() {
			t.SetBroke(true)
		}
		return s
	}

	if recv != nil {
		recv.Offset = BOGUS_FUNARG_OFFSET
	}
	unzeroFieldOffsets(params)
	unzeroFieldOffsets(results)
	ft.Receiver = funargs(recvs, FunargRcvr)
	// TODO（danscales）：如果没有tparams 
	ft.TParams = funargs(tparams, FunargTparams)
	ft.Params = funargs(params, FunargParams)
	ft.Results = funargs(results, FunargResults)
	ft.pkg = pkg
	if len(tparams) > 0 || fieldsHasTParam(recvs) || fieldsHasTParam(params) ||
		fieldsHasTParam(results) {
		t.SetHasTParam(true)
	}
	if fieldsHasShape(recvs) || fieldsHasShape(params) || fieldsHasShape(results) {
		t.SetHasShape(true)
	}

	return t
}

// NewStruct返回一个带有给定字段的新结构，只需在此处使用nil（节省内存）。
func NewStruct(pkg *Pkg, fields []*Field) *Type {
	t := newType(TSTRUCT)
	t.SetFields(fields)
	if anyBroke(fields) {
		t.SetBroke(true)
	}
	t.extra.(*Struct).pkg = pkg
	if fieldsHasTParam(fields) {
		t.SetHasTParam(true)
	}
	if fieldsHasShape(fields) {
		t.SetHasShape(true)
	}
	return t
}

func anyBroke(fields []*Field) bool {
	for _, f := range fields {
		if f.Broke() {
			return true
		}
	}
	return false
}

var (
	IsInt     [NTYPE]bool
	IsFloat   [NTYPE]bool
	IsComplex [NTYPE]bool
	IsSimple  [NTYPE]bool
)

var IsOrdered [NTYPE]bool

// IsReflexive报告t是否有自反等式运算符。
// 也就是说，如果t类型的所有x的x=x。
func IsReflexive(t *Type) bool {
	switch t.Kind() {
	case TBOOL,
		TINT,
		TUINT,
		TINT8,
		TUINT8,
		TINT16,
		TUINT16,
		TINT32,
		TUINT32,
		TINT64,
		TUINT64,
		TUINTPTR,
		TPTR,
		TUNSAFEPTR,
		TSTRING,
		TCHAN:
		return true

	case TFLOAT32,
		TFLOAT64,
		TCOMPLEX64,
		TCOMPLEX128,
		TINTER:
		return false

	case TARRAY:
		return IsReflexive(t.Elem())

	case TSTRUCT:
		for _, t1 := range t.Fields().Slice() {
			if !IsReflexive(t1.Type) {
				return false
			}
		}
		return true

	default:
		base.Fatalf("bad type for map key: %v", t)
		return false
	}
}

// 这个类型可以直接存储在接口字中吗？
// 是，如果表示为单指针。
func IsDirectIface(t *Type) bool {
	if t.Broke() {
		return false
	}

	switch t.Kind() {
	case TPTR:
		// 指向notinheap类型的指针必须间接存储。见第42076期。
		return !t.Elem().NotInHeap()
	case TCHAN,
		TMAP,
		TFUNC,
		TUNSAFEPTR:
		return true

	case TARRAY:
		// 1 direct iface类型的数组可以是direct。
		return t.NumElem() == 1 && IsDirectIface(t.Elem())

	case TSTRUCT:
		// 带有1个direct iface类型字段的结构可以是direct。
		return t.NumFields() == 1 && IsDirectIface(t.Field(0).Type)
	}

	return false
}

// IsInterfaceMethod报告（字段）m是否为
// 接口方法。这种方法有
// 特殊接收器类型。FakeRecvType（）。
func IsInterfaceMethod(f *Type) bool {
	return f.Recv().Type == FakeRecvType()
}

// IsMethodAdapplicable报告是否可以对t类型的
// 值调用方法m。这是必要的，因为我们为t和*t计算单个
// 方法集，但有些*t方法不适用于t接收器。
func IsMethodApplicable(t *Type, m *Field) bool {
	return t.IsPtr() || !m.Type.Recv().Type.IsPtr() || IsInterfaceMethod(m.Type) || m.Embedded == 2
}

// IsRuntimePkg报告p是否为包运行时。
func IsRuntimePkg(p *Pkg) bool {
	if base.Flag.CompilingRuntime && p == LocalPkg {
		return true
	}
	return p.Path == "runtime"
}

// IsReflectPkg报告p是否为包反射。
func IsReflectPkg(p *Pkg) bool {
	if p == LocalPkg {
		return base.Ctxt.Pkgpath == "reflect"
	}
	return p.Path == "reflect"
}

// ReceiverBaseType返回底层类型（如果有），即拥有带有接收方参数t的方法的
// 结果是命名类型或匿名结构。
func ReceiverBaseType(t *Type) *Type {
	if t == nil {
		return nil
	}

	// 如果指针在那里，就把它拿走。
	if t.IsPtr() {
		if t.Sym() != nil {
			return nil
		}
		t = t.Elem()
		if t == nil {
			return nil
		}
	}

	// 必须是命名类型或匿名结构。
	if t.Sym() == nil && !t.IsStruct() {
		return nil
	}

	// 检查类型。
	if IsSimple[t.Kind()] {
		return t
	}
	switch t.Kind() {
	case TARRAY, TCHAN, TFUNC, TMAP, TSLICE, TSTRING, TSTRUCT:
		return t
	}
	return nil
}

func FloatForComplex(t *Type) *Type {
	switch t.Kind() {
	case TCOMPLEX64:
		return Types[TFLOAT32]
	case TCOMPLEX128:
		return Types[TFLOAT64]
	}
	base.Fatalf("unexpected type: %v", t)
	return nil
}

func ComplexForFloat(t *Type) *Type {
	switch t.Kind() {
	case TFLOAT32:
		return Types[TCOMPLEX64]
	case TFLOAT64:
		return Types[TCOMPLEX128]
	}
	base.Fatalf("unexpected type: %v", t)
	return nil
}

func TypeSym(t *Type) *Sym {
	return TypeSymLookup(TypeSymName(t))
}

func TypeSymLookup(name string) *Sym {
	typepkgmu.Lock()
	s := typepkg.Lookup(name)
	typepkgmu.Unlock()
	return s
}

func TypeSymName(t *Type) string {
	name := t.LinkString()
	// 为#17752的Noalg类型使用单独的符号名。
	if TypeHasNoAlg(t) {
		name = "noalg." + name
	}
	return name
}

// 运行时类型信息（标题）的假包
// 不要直接访问，使用下面的typeLookup。
var (
	typepkgmu sync.Mutex // 保护typepkg查找
	typepkg   = NewPkg("type", "type")
)

var SimType [NTYPE]Kind

// 形状类型的假包（请参阅typecheck.Shapify（））。
var ShapePkg = NewPkg("go.shape", "go.shape")
